package top.chmin.project.cloud.common.tool;


import org.apache.commons.lang3.StringUtils;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

public class DatetimeTool {

    public static String format(LocalDateTime date) {
        if (date == null) {
            return null;
        }
        return format(date, DateFormat.datetime);
    }

    public static String format(LocalDateTime date, DateFormat format) {
        if (date == null) return "";
        return DateTimeFormatter.ofPattern(format.format).format(date);
    }

    public static LocalDateTime lastDay(LocalDateTime localDateTime) {
        if (localDateTime == null) {
            return null;
        }
        return localDateTime.toLocalDate().atStartOfDay().minusDays(1);
    }

    public static LocalDateTime parseLocalDateTime(String source) {
        if (StringUtils.isBlank(source)) {
            return null;
        }
        for (DateFormat format : DateFormat.values()) {
            try {
                return LocalDateTime.parse(source, DateTimeFormatter.ofPattern(format.format));
            } catch (Exception ignored) {
            }
        }
        return null;
    }

    public static int stamp() {
        return (int) (System.currentTimeMillis() / 1000);
    }

    public static LocalDateTime getYearFirstDayWithSameTime() {
        return LocalDateTime.now().withDayOfYear(1);
    }

    public static LocalDateTime getYearFirstDayWithSameTime(LocalDateTime date) {
        return date.withDayOfYear(1);
    }

    public static LocalDateTime getQuarterFirstDayWithSameTime() {
        return LocalDateTime.now().withMonth(LocalDateTime.now().getMonth().getValue() / 3 * 3);
    }

    public static LocalDateTime getQuarterFirstDayWithSameTime(LocalDateTime date) {
        if (date == null) {
            return null;
        }
        return date.withMonth(date.getMonth().getValue() / 3 * 3);
    }

    public static LocalDateTime getMonthFirstDayWithSameTime() {
        return LocalDateTime.now().withDayOfMonth(1);
    }

    public static LocalDateTime getMonthFirstDayWithSameTime(LocalDateTime date) {
        return date.withDayOfMonth(1);
    }

    public static LocalDateTime getDateWithoutTimeInfo() {
        return LocalDate.now().atStartOfDay();
    }

    public static LocalDateTime getDateWithoutTimeInfo(LocalDateTime date) {
        if (date == null) {
            return null;
        }
        return date.toLocalDate().atStartOfDay();
    }

    public static LocalDateTime nextDay(LocalDateTime date) {
        if (date == null) {
            return null;
        }
        return date.toLocalDate().atStartOfDay().minusDays(-1);
    }

    public static LocalDateTime getDateWithoutTimeInfoBefore(int days) {
        LocalDateTime today = getDateWithoutTimeInfo();
        return today.minusDays(days);
    }


    public static LocalDateTime getLocalDateTimeWithoutTimeInfoAfter(int days) {
        LocalDateTime now = getDateWithoutTimeInfo();
        return now.minusDays(-days);
    }

    public static LocalDateTime getLocalDateTimeBeforeSecond(int second) {
        LocalDateTime now = LocalDateTime.now();
        return now.minusSeconds(second);
    }

    public static LocalDateTime getLocalDateTimeAfterSecond(int second) {
        LocalDateTime now = LocalDateTime.now();
        return now.minusSeconds(-second);
    }

    public static boolean isSameDay(LocalDateTime one, LocalDateTime two) {
        if (one == null || two == null) {
            return false;
        }
        return StringUtils.equals(format(one, DateFormat.date), format(two, DateFormat.date));
    }

    public static boolean isNotSameDay(LocalDateTime one, LocalDateTime two) {
        return !isSameDay(one, two);
    }

    public static boolean isSameWeek(LocalDateTime one, LocalDateTime two) {
        if (one == null || two == null) {
            return false;
        }
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("w");
        return one.getYear() == two.getYear() && StringUtils.equals(one.format(formatter), two.format(formatter));
    }

    public static String dayOfWeek(LocalDateTime date) {
        String[] weekDays = {"一", "二", "三", "四", "五", "六", "日"};
        return weekDays[date.getDayOfWeek().getValue() - 1];
    }

    public static String dayOfWeekNub(LocalDateTime date) {
        String[] weekDays = {"1", "2", "3", "4", "5", "6", "7"};
        return weekDays[date.getDayOfWeek().getValue() - 1];
    }

    public enum DateFormat {
        datetime("yyyy-MM-dd HH:mm:ss"),
        datetimeWithoutSecond("yyyy-MM-dd HH:mm"),
        date("yyyy-MM-dd"),
        month("HH:mm:ss"),
        birth("yyyy-MM"),
        compactDateTime("yyyyMMddHHmmss"),
        compactTime("HHmmss"),
        compactDate("yyyyMMdd"),
        hourMinute("HH:mm");

        public final String format;

        DateFormat(String format) {
            this.format = format;
        }
    }

}
